package com.googlecode.gwt_control.client.form;

import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Olafur Gauti Gudmundsson
 */
public class FieldSection extends Composite {

    private final int COLCOUNT = 2;

    private final Panel container;
    private final FlexTable table;
    private final Map<String,FieldInfo> fields;
    private final FieldPanel fieldPanel;
    private final Label titleLabel, descriptionLabel;

    FieldSection( String title, String description, FieldPanel fieldPanel ) {
        this.fieldPanel = fieldPanel;
        this.table = new FlexTable();
        this.container = new FlowPanel();
        container.setStyleName("fieldSectionContainer");
        table.setStyleName("fieldSection");
        table.setCellPadding(0);
        table.setCellSpacing(0);
        this.fields = new HashMap<String,FieldInfo>();

        // add title to table
        titleLabel = new Label();
        titleLabel.setStyleName("title");
        if ( title != null && title.trim().length() > 0 ) {
            titleLabel.setText(title);

            int newRow = table.getRowCount();
            table.setWidget(newRow, 0, titleLabel);
            table.getRowFormatter().addStyleName(newRow, "fieldSectionTitleRow");
            table.getFlexCellFormatter().setColSpan(newRow, 0, COLCOUNT);
        }

        // add description to table
        descriptionLabel = new Label();
        descriptionLabel.setStyleName("description");
        if ( description != null && description.trim().length() > 0 ) {
            descriptionLabel.setText(description);

            int newRow = table.getRowCount();
            table.setWidget(newRow, 0, descriptionLabel);
            table.getRowFormatter().addStyleName(newRow, "fieldSectionDescRow");
            table.getFlexCellFormatter().setColSpan(newRow, 0, COLCOUNT);
        }

        container.add(table);

        initWidget(container);
    }

    public void add( Field field ) {
        int newRow = table.getRowCount();

        field.addToTable(newRow, table);
        table.getRowFormatter().addStyleName(newRow, "fieldSectionRow");

        FieldInfo fieldInfo = new FieldInfo(newRow, field);
        fields.put(field.getId(), fieldInfo);
        field.onAttach(fieldPanel);
    }

    public void addInfo( HTML infoHTML ) {
        Panel infoPanel = new FlowPanel();
        infoPanel.setStyleName("info");
        infoPanel.add(infoHTML);

        int newRow = table.getRowCount();
        table.setWidget(newRow, 0, infoPanel);
        table.getRowFormatter().addStyleName(newRow, "fieldSectionInfoRow");
        table.getFlexCellFormatter().setColSpan(newRow, 0, COLCOUNT);
    }

    public void addButton( Button button ) {
        List<Button> buttons = new ArrayList<Button>();
        buttons.add(button);
        addButtons(buttons);
    }

    public void addButtons( List<Button> buttons ) {
        Panel buttonPanel = new HorizontalPanel();
        buttonPanel.setStyleName("buttons");
        for ( Button button : buttons ) {
            buttonPanel.add(button);
        }

        int newRow = table.getRowCount();
        table.setWidget(newRow, 0, buttonPanel);
        table.getRowFormatter().addStyleName(newRow, "fieldSectionButtonRow");
        table.getFlexCellFormatter().setColSpan(newRow, 0, COLCOUNT);
    }

    public void setFieldVisible( String id, boolean visible ) {
        FieldInfo fieldInfo = fields.get(id);
        if ( fieldInfo != null ) {
            table.getRowFormatter().setVisible(fieldInfo.rowNumber, visible);
        }
    }

    public Field findField( String id ) {
        FieldInfo fieldInfo = fields.get(id);
        if ( fieldInfo != null ) {
            return fieldInfo.field;
        } else {
            return null;
        }
    }

    List<Field> getFields() {
        List<Field> fieldList = new ArrayList<Field>();
        for ( Map.Entry<String,FieldInfo> entry : fields.entrySet() ) {
            fieldList.add(entry.getValue().field);
        }
        return fieldList;
    }

    public Label getDescriptionLabel() {
        return descriptionLabel;
    }

    public Label getTitleLabel() {
        return titleLabel;
    }

    private class FieldInfo {
        int rowNumber;
        Field field;

        FieldInfo( int rowNumber, Field field ) {
            this.rowNumber = rowNumber;
            this.field = field;
        }
    }

}
